/**
 * Widget Meteo : Projet Android 
 * @author Floriance BRIN, Julie ESCOFFIER, Yoann GOBERT, Ikram NACIRI, Yann NIVET
 * @version 1.0
 * @date mars 2011
 * **/

package fr.imac.ProjetAndroid;


import fr.imac.ProjetAndroid.citySearch.CityList;
import fr.imac.ProjetAndroid.favoritesGestion.Favorite;
import fr.imac.ProjetAndroid.favoritesGestion.FavoriteProvider;
import fr.imac.ProjetAndroid.weatherGestion.WeatherConditions;
import fr.imac.ProjetAndroid.weatherGestion.WeatherReader;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.appwidget.AppWidgetManager;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;


import android.content.SharedPreferences;

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TextView;

public class ProjetAndroidActivity extends Activity {
	
	private WeatherReader myWeather;
	private ProgressDialog progressDialogUpdate;
	private ProgressDialog progressDialogCityList;
	
	//private Builder citySearchDialogBuilder;
	private AlertDialog citySearchDialog;
	private CityList listeVilles;
	private Button choixVille;
	private EditText texteVilleRecherche;
	
	// Permet de recupérer les longitudes/latitudes du mobile
	private Geolocation myGeolocation;
	private boolean isGPS;
	private boolean isWeather;
	private String theme;
	private SharedPreferences settings;
	private SharedPreferences.Editor editor;
	private MenuItem itemGeolocation;
	private Button favoriteButton;
	private FavoriteProvider favoriteProvider;
	private Favorite currentMeteo;
	private int utiliseGeoloc;
	private Boolean actualise;
	private ProjetAndroidActivity referenceApplication = this;
	private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);					// Initialisation de l'interface graphique
        actualise = true;
        //initialise la Geolocalisation
        // pour afficher les Log ajouter un filtre avec comme tag "toto" -_^
        this.setMyGeolocation(new Geolocation(this));
        

        // Definit les préférences en fonction du menu settings
        settings = getSharedPreferences(SettingsActivity.PREFS_NAME, 0);        
        editor = settings.edit();
        
        // On définit la météo courante en fonction de la dernière meteo visualisé avt de ferme l'appli
        currentMeteo = new Favorite(); 


        //création de notre boite de chargement pour l'update
        progressDialogUpdate = new ProgressDialog(this);
        progressDialogUpdate.setTitle("");
        progressDialogUpdate.setMessage(getString(R.string.updateData));
        
        //création de notre boite de chargement pour la liste des villes
        progressDialogCityList = new ProgressDialog(this);
        progressDialogCityList.setTitle("");
        progressDialogCityList.setMessage(getString(R.string.searchCitySearching));
        
        //création de la liste des villes proposées à l'utilisateur
        listeVilles = new CityList();  
        //création de la fenêtre pour la recherche de villes
        initCitySearch();
        
        
        favoriteButton = (Button) findViewById(R.id.favoriteButton);
        favoriteProvider = new FavoriteProvider(this);
     
		if(favoriteProvider.alreadyExist(currentMeteo.name)==0)
			favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_off);
		else
	        favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_on);

        favoriteButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				if(favoriteProvider.alreadyExist(currentMeteo.name)==0)
				{
					favoriteProvider.insert(currentMeteo);
					favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_on);
				}
				else
				{
					favoriteProvider.deleteByName(currentMeteo.name);
			        favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_off);
				}
			}
		});
        
        // Find widget id from launching intent
       	Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }
 
        // If they gave us an intent without the widget id, just bail.
        
        if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
            Log.e("toto", "Configuration Activity: no appwidget id provided");
         //   finish();
        }
    }
    
    /**
     * Fonction qui génère un favori
     * @param city : le nom de la ville
     * @param code : son code
     * @param isZipCode : si c'est une ville des USA
     */
    private void setFavorite(String city, int code, boolean isZipCode){
    	currentMeteo = new Favorite();
        currentMeteo.name=city;
        currentMeteo.isMyFavorite = false;
        currentMeteo.code = code;
        currentMeteo.isZipCode = isZipCode;
        
        if(favoriteProvider.alreadyExist(currentMeteo.name)==0)
			favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_off);
		else
	        favoriteButton.setBackgroundResource(android.R.drawable.btn_star_big_on);
    }
    
    /**
     * fonction qui actualise l'affichage de la fenêtre principale
     */
    private void updateDisplayMeteo(Boolean setCityName) {
    	//pour obtenir les conditions météo actuelles
        WeatherConditions conditionsActuelles = myWeather.getCurrentWeatherCondition();
        //pour obtenir les prévisions
        WeatherConditions[] previsions = myWeather.getAllWeatherPrevisions();
       
       if(setCityName) setDisplayCityName(myWeather.getCity());
       
       /**
        * Mise a jour affichage des conditions meteo
        * **/
        conditionsActuelles.calculJoursPrevisions((TextView)findViewById(R.id.tendances_Jplus1_JOUR), (TextView)findViewById(R.id.tendances_Jplus2_JOUR), (TextView)findViewById(R.id.tendances_Jplus3_JOUR), (TextView)findViewById(R.id.tendances_Jplus4_JOUR));        
       
        conditionsActuelles.updateDisplayCurrent( ((TextView)findViewById(R.id.temperature_Jour)), ((ImageView)findViewById(R.id.imageMeteo_Jour)), ((TextView)findViewById(R.id.miseAjour)), ((TextView)findViewById(R.id.jourCourant)));
        previsions[0].updateDisplayPrevision1( ((ImageView)findViewById(R.id.tendances_Jplus1_IMG)), ((TextView)findViewById(R.id.tendances_Jplus1_TEMP)));
        previsions[1].updateDisplayPrevision2( ((ImageView)findViewById(R.id.tendances_Jplus2_IMG)), ((TextView)findViewById(R.id.tendances_Jplus2_TEMP)));
        previsions[2].updateDisplayPrevision3( ((ImageView)findViewById(R.id.tendances_Jplus3_IMG)), ((TextView)findViewById(R.id.tendances_Jplus3_TEMP)));
        previsions[3].updateDisplayPrevision4( ((ImageView)findViewById(R.id.tendances_Jplus4_IMG)), ((TextView)findViewById(R.id.tendances_Jplus4_TEMP)));

    }
    /**
     * définit le nom de ville à afficher dans la fenêtre principale
     * @param name : le nom de la ville
     */
    private void setDisplayCityName(String name){
    	TextView cityName = (TextView)findViewById(R.id.currentCityName);
        cityName.setText(name);
    }
    @Override
    public void onStart() {   
    	super.onStart();
    	//Log.i("toto", "onStart appli");
    	theme = settings.getString("theme", SettingsActivity.THEME_1);
        isGPS = settings.getBoolean("isGPS", true);
        setWeather(settings.getBoolean("isWeather", true));
        LinearLayout l = (LinearLayout) findViewById(R.id.layoutMain);
        TableLayout t = (TableLayout) findViewById(R.id.tableMain);
        
		if(theme==SettingsActivity.THEME_1){
			l.setBackgroundResource(R.drawable.bg);
			t.setBackgroundResource(R.drawable.bgtitreville);
		} else {
			l.setBackgroundResource(R.drawable.bg_);
			t.setBackgroundResource(R.drawable.bgtitreville_);
		}
        
        
        Log.i("toto", "valeur du checkbox "+isGPS);
        if(!isGPS) {
        	Log.i("toto", "GSP disable PROJECTANDROIDACTIVITY ");
        	myGeolocation.stopGeolocation();
        	if(itemGeolocation!=null) itemGeolocation.setEnabled(false);
        	
        } else {
        	Log.i("toto", "GSP enable PROJECTANDROIDACTIVITY ");
        	myGeolocation.requestPosition();
        	if(itemGeolocation!=null) itemGeolocation.setEnabled(true);
        }
        Boolean wasInFavorites = settings.getBoolean("wasInFavorites", false);
        if(wasInFavorites){
        	editor.putBoolean("wasInFavorites", false);
        	Boolean actu = settings.getBoolean("actualise", false);
        	actualise = actu;
        }
        
       
        currentMeteo.name= settings.getString("meteoCourante_nom","Paris");
        int meteoCourante_isMyFavorite = settings.getInt("meteoCourante_isMyFavorite",0);
        if(meteoCourante_isMyFavorite == 0) currentMeteo.isMyFavorite=false;
        else currentMeteo.isMyFavorite = true;
        currentMeteo.code = settings.getInt("codeMeteoCourante", 62827);
        int meteoCourante_isZipCode =  settings.getInt("meteoCourante_isZipCode",0);
        if(meteoCourante_isZipCode == 0) currentMeteo.isZipCode=false;
        else currentMeteo.isZipCode = true;
        setFavorite(currentMeteo.name, 
        		currentMeteo.code, 
				currentMeteo.isZipCode);
        
        
        if(actualise){
	        myWeather = new WeatherReader(currentMeteo.code, currentMeteo.isZipCode);
	        setDisplayCityName(currentMeteo.name);
		       
	        this.updateWeatherData(false);
        }
        
    }

    @Override
    public void onResume() {
    	//Log.i("toto", "onResume appli");
    	super.onResume();
    }

    @Override
    public void onPause() {
    	//Log.i("toto", "onPause appli");
    	super.onPause();
    }

    @Override
    public void onStop() {
    	super.onStop();
    	
    	editor.putString("meteoCourante_nom", currentMeteo.name);
    	
    	if(currentMeteo.isMyFavorite) editor.putInt("meteoCourante_isMyFavorite",1);
    	else editor.putInt("meteoCourante_isMyFavorite",0);
    	
    	if(currentMeteo.isZipCode) editor.putInt("meteoCourante_isZipCode",1);
    	else editor.putInt("meteoCourante_isZipCode",0);
    	
    	editor.putInt("codeMeteoCourante", currentMeteo.code);
    	editor.putInt("utiliseGeoloc", utiliseGeoloc);
    	
    	editor.putBoolean("actualise", true);
    	editor.commit();  
    	if(WidgetMeteo.widget !=null) WidgetMeteo.widget.onUpdate(null, null, null);
    	//configureWidget(this.getApplicationContext());
    	    	
    }
    
    @Override
    public void onDestroy() {
    	//Log.i("toto", "onDestroy appli");
    	super.onDestroy();
    }
    
	/**
	 * Creation des boites de dialogue
	 */
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
			/**case DIALOG_ID:
				AlertDialog.Builder dialog = new AlertDialog.Builder(this);
				dialog.setTitle(R.string.import_export);
				dialog.setIcon(android.R.drawable.ic_dialog_info);
				dialog.setItems(R.array.import_export,null);
				dialog.setPositiveButton(android.R.string.ok, null);
				dialog.setNegativeButton(android.R.string.cancel, null);
				dialog.create();

				return dialog;
				break;
			**/
			default:	
				return super.onCreateDialog(id);
		}
	}
	
	
	/**
	 * Methode pour la creation du menu {@link Menu}
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// permet de charger le fichier XML du menu
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.weather_menu, menu);
		itemGeolocation = menu.findItem(R.id.menu_item_geolocation);
		if(!isGPS) {
			Log.i("toto", "GSP disable PROJECTANDROIDACTIVITY ");
			itemGeolocation.setEnabled(false);

		} else {
			Log.i("toto", "GSP enable PROJECTANDROIDACTIVITY ");
			itemGeolocation.setEnabled(true);
		}
		return true;
	}

	/**
	 * M�thode appel�e quand l'utilisateur s�lectionne un item du menu
	 */
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {

		switch (item.getItemId()) {
		case R.id.menu_item_settings:
				actualise = false;
				Intent intent=new Intent(this, SettingsActivity.class);
				// Lancement de l'activit�. La courante n'�tant pas termin�e, elle est ajout�e � la pile.
				startActivity(intent);
			break;

		case R.id.menu_item_upload :
			//mise à jour de nos données
			actualise = true;
			//setDisplayCityName(currentMeteo.name);
			
			updateWeatherData(false);
			
			this.updateDisplayMeteo(false);

			break;

		case R.id.menu_item_favorite:
			actualise = true;
				Intent intent1=new Intent(this, FavoritesPreferenceActivity.class);
				// Lancement de l'activit�. La courante n'�tant pas termin�e, elle est ajout�e � la pile.
				startActivity(intent1);
			break;
		
		case R.id.menu_item_geolocation :
			actualise = true;
			utiliseGeoloc = 1;
	        myWeather = new WeatherReader(myGeolocation.getLatitude(), myGeolocation.getLongitude());
	       // setDisplayCityName(currentMeteo.name);
	        
	        this.updateWeatherData(true);
	        
	        setFavorite(myWeather.getCity(), 
	        		myWeather.getCode(), 
	        		myWeather.getIsZipCode()); 
			
			break;
		case R.id.menu_item_search:
			actualise = true;
			//on réinitialise les valeurs de la boite
			choixVille.setText(listeVilles.getListeVilles().get(0).ville+", "+listeVilles.getListeVilles().get(0).pays);
			texteVilleRecherche.setText("");
			citySearchDialog.show();
			break;

		default:
			break;
		}
		return true;
	}
	/**
	 * Fonction qui récupère les villes et les pays d'une CityList et qui les convertit en tableau de String
	 * @param liste :CityList
	 * @return : le tableau de String formatées ainsi : "ville, pays"
	 */
	private String[] cityListToStringArray(CityList liste){
		String[] arrayCityList = new String[liste.getListeVilles().size()];
        for(int i=0; i<liste.getListeVilles().size(); i++){
        	String ville = liste.getListeVilles().get(i).ville;
        	String pays = liste.getListeVilles().get(i).pays;
        	arrayCityList[i] = ville+", "+pays;
        }
        return arrayCityList;
	}
	/**
	 * Fonction qui crée la fenêtre pour la recherche des villes
	 */
	private void initCitySearch(){
		//création de la fenêtre de dialogue pour la recherche de ville
        LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.citysearcher,
                                       (ViewGroup) findViewById(R.id.layoutCitySearcher));
        Builder citySearchDialogBuilder = new AlertDialog.Builder(this);
        citySearchDialogBuilder.setView(layout);
        
        //gestion du bouton de choix des villes
        choixVille = (Button) layout.findViewById(R.id.buttonCitySearch);
        choixVille.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				String[] propositionVille = cityListToStringArray(listeVilles);
				
				AlertDialog.Builder builder = new AlertDialog.Builder(referenceApplication);
				builder.setTitle(R.string.searchCityResult);
				builder.setItems(propositionVille, new DialogInterface.OnClickListener() {
				    public void onClick(DialogInterface dialog, int item) {
				    	citySearchDialog.dismiss();
				    	boolean isZipCode = listeVilles.getListeVilles().get(item).isZipCode;
						String code = listeVilles.getListeVilles().get(item).code;
						myWeather = new WeatherReader(code, isZipCode);
						myWeather.setCity(listeVilles.getListeVilles().get(item).ville);
						setFavorite(myWeather.getCity(), 
								Integer.parseInt(code), 
								isZipCode);
						//actualisation de l'affichage
						updateWeatherData(false);
						setDisplayCityName(currentMeteo.name);
						
				    }
				});
				AlertDialog alertListVilleDefaut = builder.create();
				alertListVilleDefaut.show();
			}
        	
        });
        
        texteVilleRecherche = (EditText)layout.findViewById(R.id.searchCityInputText);
        
        //gestion du bouton annuler
        Button boutonAnnule = (Button) layout.findViewById(R.id.searchCitySearchCancel);
        boutonAnnule.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View arg0) {
				citySearchDialog.dismiss();
			}
        	
        });
        
        //gestion du bouton rechercher
        Button boutonRecherche = (Button) layout.findViewById(R.id.searchCitySearchBtn);
        boutonRecherche.setOnClickListener(new OnClickListener(){
        	
			@Override
			public void onClick(View arg0) {
				citySearchDialog.dismiss();
				//on choisit le mode adapté. si l'utilisateur a écrit quelque-chose on passe en mode recherche de ville
				if(texteVilleRecherche.getText().length()>0){
					progressDialogCityList.show();
					new LoadCity().execute();
				}
			}
        	
        });
        
        citySearchDialog =citySearchDialogBuilder.create();
	}
	
	/**
	 * @param myGeolocation the myGeolocation to set
	 */
	public void setMyGeolocation(Geolocation myGeolocation) {
		this.myGeolocation = myGeolocation;
	}

	/**
	 * @return the myGeolocation
	 */
	public Geolocation getMyGeolocation() {
		return myGeolocation;
	}
	
	/**
	 * Fonction qui affiche une alertBox
	 * @param title : le titre de la fenetre
	 * @param mymessage : le message
	 */
	public void alertbox(String title, String myMessage){
		new AlertDialog.Builder(this)
			.setMessage(myMessage)
			.setTitle(title)
			.setIcon(android.R.drawable.ic_dialog_alert)
			.setCancelable(true)
			.setNeutralButton(android.R.string.ok,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int whichButton){}
				}).show();
	}
	/**
	 * Fonction qui affiche un message d'erreur lorsqu'il n'y a pas de connexion internet
	 */
	public void erreurConnexion(){
		alertbox("Oups !", getString(R.string.errorConnexion));
	}
	/**
	 * Fonction qui recharge toutes les données météo
	 * @param updateCityName : on update le nom de la ville
	 */
	private void updateWeatherData(boolean updateCityName){
		progressDialogUpdate.show();
		Log.i("toto","ici ça passe");
		new LoadData(updateCityName).execute();
		
	}
	class LoadData extends AsyncTask<Void, Void, Void>{
		private boolean erreurConnexion=false;
		private boolean updateCity = true;
		LoadData(){
			super();
		}
		LoadData(boolean updateCity){
			super();
			this.updateCity = updateCity;
			
		}
		@Override
		protected Void doInBackground(Void... params) {
			try{
				myWeather.updateAll(updateCity);
			}catch(Exception e){
				Log.e("WeatherReader","erreur chargement : "+e.toString());
				erreurConnexion = true;
			}
			return null;
		}
		@Override
		protected void onPostExecute(Void result) {
			if(progressDialogUpdate.isShowing()){
				progressDialogUpdate.dismiss();
			}
			if(erreurConnexion){
				erreurConnexion();
			}else{
				updateDisplayMeteo(updateCity);	
				if(updateCity) {
					currentMeteo.name = myWeather.getCity();
					currentMeteo.code = myWeather.getCode();
					currentMeteo.isZipCode = myWeather.getIsZipCode();
					currentMeteo.isMyFavorite = false;
					//currentMeteo.code = myWeather.
				}
			}
		}
	}
	class LoadCity extends AsyncTask<Void, Void, Void>{
		private boolean erreurConnexion=false;
		AlertDialog alert;
		CityList maListe;
		@Override
		protected Void doInBackground(Void... params) {
			try{
				maListe = new CityList(texteVilleRecherche.getText().toString());
				
			}catch(Exception e){
				Log.e("WeatherReader","erreur chargement : "+e.toString());
				erreurConnexion = true;
			}
			return null;
		}
		@Override
		protected void onPostExecute(Void result) {
			if(progressDialogCityList.isShowing()){
				progressDialogCityList.dismiss();
			}	
			if(erreurConnexion){
				erreurConnexion();
			}else{
				String[] propositionVille = cityListToStringArray(maListe);
				
				AlertDialog.Builder builder = new AlertDialog.Builder(referenceApplication);
				builder.setTitle(R.string.searchCityResult);
				builder.setItems(propositionVille, new DialogInterface.OnClickListener() {
				    public void onClick(DialogInterface dialog, int item) {
				    	
				    	boolean isZipCode = maListe.getListeVilles().get(item).isZipCode;
						String code = maListe.getListeVilles().get(item).code;
						myWeather = new WeatherReader(code, isZipCode);
						myWeather.setCity(maListe.getListeVilles().get(item).ville);
						setFavorite(myWeather.getCity(), 
								Integer.parseInt(code), 
								isZipCode);
						Log.i("toto", myWeather.getCity());
						//actualisation de l'affichage
						updateWeatherData(false);
						setDisplayCityName(currentMeteo.name);
						
				    }
				});
				alert = builder.create();
				alert.show();
			}
			//super.onPostExecute(result);
		}
	}
    /**
     * Configures the created widget
     * @param context
     */
    public void configureWidget(Context context) {
    	
       AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
       WidgetMeteo.updateAppWidget(context, appWidgetManager, mAppWidgetId);
    }

	/**
	 * @param isWeather the isWeather to set
	 */
	public void setWeather(boolean isWeather) {
		this.isWeather = isWeather;
	}

	/**
	 * @return the isWeather
	 */
	public boolean isWeather() {
		return isWeather;
	}
}
	
